package com.cocolover2.andbase.utils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.media.ExifInterface;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
import android.text.TextUtils;

import com.jakewharton.disklrucache.Util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("unused")
public class ImageUtil {
    private ImageUtil() {
        throw new UnsupportedOperationException("cannot be instantiated");
    }

    /**
     * 压缩图片(像素压缩)
     *
     * @param path          图片路径
     * @param requestWidth  压缩后的宽度
     * @param requestHeight 压缩后的高度
     */
    public static Bitmap compressImgBySize(String path, int requestWidth, int requestHeight) {
        if (TextUtils.isEmpty(path) || !new File(path).exists())
            return null;
        //第一次解析图片的时候将inJustDecodeBounds设置为true,来获取图片的大小
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(path, options);
        options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight);
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeFile(path, options);
    }

    /**
     * 压缩图片(像素压缩)
     *
     * @param bitmap        图片
     * @param requestWidth  压缩后的宽度
     * @param requestHeight 压缩后的高度
     */
    public static Bitmap compressImgBySize(Bitmap bitmap, int requestWidth, int requestHeight) {
        if (bitmap == null)
            return null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.outWidth = bitmap.getWidth();
        options.outHeight = bitmap.getHeight();
        options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight);
        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        return BitmapFactory.decodeStream(inputStream, null, options);
    }

    private static int calculateInSampleSize(BitmapFactory.Options options, int requestWidth, int requestHeight) {
        int width = options.outWidth;
        int height = options.outHeight;
        int inSampleSize = 1;
        if (width > requestWidth || height > requestHeight) {
            final int heightRatio = Math.round((float) height / (float) requestHeight);
            final int widthRatio = Math.round((float) width / (float) requestWidth);
            inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
        }
        return inSampleSize;
    }


    public interface OnCompressedListener {
        void onCompressed(String compressedPath);
    }

    public interface OnCompressImgsListener {
        void onCompressedImgs(ArrayList<String> imgPaths);
    }

    /**
     * 压缩单张图片(质量压缩)
     *
     * @param context  上下文环境
     * @param bitmap   原始图片
     * @param size     压缩后大小(单位:字节)
     * @param listener 压缩成功后的回调
     */
    public static void compressImgByQualiy(final Context context, final Bitmap bitmap, final long size, final OnCompressedListener listener) {
        if (bitmap == null)
            throw new NullPointerException("bitmap can not be null");


        HandlerThread thread = new HandlerThread("compress-quality-thread");
        thread.start();
        final Handler _handler = new Handler(thread.getLooper(), new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                final String _path = compressImageByQuality(context, bitmap, size);
                if (listener != null) {
                    listener.onCompressed(_path);
                }
                return true;
            }
        });
        _handler.sendEmptyMessage(0);
    }

    /**
     * 批量压缩图片(质量压缩)
     *
     * @param context  上下文环境
     * @param sources  原始图片路径集合
     * @param size     压缩后的图片大小(单位:字节)
     * @param listener 压缩完成后的回调
     */
    public static void compressPicsByQualiy(final Context context, final List<String> sources, final long size, final OnCompressImgsListener listener) {
        if (sources == null)
            throw new NullPointerException("sources can not be null");

        HandlerThread thread = new HandlerThread("compress-quality-thread");
        thread.start();
        final Handler _handler = new Handler(thread.getLooper(), new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                ArrayList<String> lists = new ArrayList<>();
                for (String path : sources) {
                    final Bitmap bitmap = compressImgBySize(path, 480, 800);
                    final String _path = compressImageByQuality(context, bitmap, size);
                    lists.add(_path);
                }
                if (listener != null) {
                    listener.onCompressedImgs(lists);
                }
                return true;
            }
        });
        _handler.sendEmptyMessage(0);
    }


    /**
     * Compress by quality,  and generate image to the path specified
     *
     * @param image   原始图片
     * @param maxSize 单位:字节
     */
    public static String compressImageByQuality(Context context, Bitmap image, long maxSize) {

        File dirFile = FileUtil.getCacheDir(context, "compress");
        File jpegTrueFile = new File(dirFile, "IMG_" + System.currentTimeMillis() + "_compress" + ".jpg");
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        // scale
        int options = 100;
        // Store the bitmap into output stream(no compress)
        image.compress(Bitmap.CompressFormat.JPEG, options, os);
        // Compress by loop
        while (os.toByteArray().length > maxSize) {
            // Clean up os
            os.reset();
            // interval 10
            options -= 4;
            image.compress(Bitmap.CompressFormat.JPEG, options, os);
        }
        FileOutputStream fos = null;
        try {
            // Generate compressed image file
            fos = new FileOutputStream(jpegTrueFile.getPath());
            fos.write(os.toByteArray());
            fos.flush();
            return jpegTrueFile.getPath();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
            Util.closeQuietly(fos);
        }
    }


    /**
     * 压缩网络图片
     * 注意：流只能使用一次，不能重复使用，可借助mark 和reset使用
     * 参考网站:http://zhangbo-peipei-163-com.iteye.com/blog/2022460
     *
     * @param is            数据流
     * @param requestWidth  压缩后的宽度
     * @param requestHeight 压缩后的高度
     */
    public static Bitmap compressBitmap(InputStream is, int requestWidth, int requestHeight) {
        if (is == null)
            return null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] bytes = new byte[1024];
        int len;
        try {
            while ((len = is.read(bytes)) > -1) {
                bos.write(bytes, 0, len);
            }
            bos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        BitmapFactory.Options options = new BitmapFactory.Options();
        ByteArrayInputStream stream = null;
        try {
            //第一次解析将inJustDecodeBounds设置为true，来获取图片大小
            options.inJustDecodeBounds = true;
            stream = new ByteArrayInputStream(bos.toByteArray());
            stream.mark(stream.available());
            BitmapFactory.decodeStream(stream, null, options);
            options.inSampleSize = calculateInSampleSize(options, requestWidth, requestHeight);
            options.inJustDecodeBounds = false;
            stream.reset();
            return BitmapFactory.decodeStream(stream, null, options);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                is.close();
                bos.close();
                if (stream != null)
                    stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    /**
     * bitmap转换成二进制
     */
    public static byte[] bitmap2Bytes(Bitmap bm) {
        if (bm == null) {
            return null;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }

    /**
     * Drawable → Bitmap
     */
    public static Bitmap drawable2Bitmap(Drawable drawable) {
        if (drawable == null) {
            return null;
        }
        // 取 drawable 的长宽
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        // 取 drawable 的颜色格式
        Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
        // 建立对应 bitmap
        Bitmap bitmap = Bitmap.createBitmap(w, h, config);
        // 建立对应 bitmap 的画布
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        // 把 drawable 内容画到画布中
        drawable.draw(canvas);
        return bitmap;
    }


    /**
     * 读取图片的旋转的角度
     *
     * @param path 图片绝对路径
     * @return 图片的旋转角度
     */
    public static int getBitmapDegree(String path) {
        int degree = 0;
        try {
            // 从指定路径下读取图片，并获取其EXIF信息
            ExifInterface exifInterface = new ExifInterface(path);
            // 获取图片的旋转信息
            int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
                case ExifInterface.ORIENTATION_ROTATE_90:
                    degree = 90;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_180:
                    degree = 180;
                    break;
                case ExifInterface.ORIENTATION_ROTATE_270:
                    degree = 270;
                    break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

    /**
     * 将图片按照某个角度进行旋转
     *
     * @param bm     需要旋转的图片
     * @param degree 旋转角度
     * @return 旋转后的图片
     */
    public static Bitmap rotateBitmapByDegree(Bitmap bm, int degree) {
        Bitmap returnBm = null;

        // 根据旋转角度，生成旋转矩阵
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);
        try {
            // 将原始图片按照旋转矩阵进行旋转，并得到新的图片
            returnBm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
        } catch (OutOfMemoryError e) {
        }
        if (returnBm == null) {
            returnBm = bm;
        }
        if (bm != returnBm) {
            bm.recycle();
        }
        return returnBm;
    }
}
